(function () {
    /**
     * @exports defined
     *
     * @param {Object} value The object.
     * @returns {Boolean} Returns true if the object is defined, returns false otherwise.
     *
     * @example
     * if (defined(positions)) {
     *      doSomething();
     * } else {
     *      doSomethingElse();
     * }
     */
    function defined(value) {
        return value !== undefined && value !== null;
    }

    /**
     * Returns the first parameter if not undefined, otherwise the second parameter.
     * Useful for setting a default value for a parameter.
     *
     * @exports defaultValue
     *
     * @param {*} a
     * @param {*} b
     * @returns {*} Returns the first parameter if not undefined, otherwise the second parameter.
     *
     * @example
     * param = Cesium.defaultValue(param, 'default');
     */
    function defaultValue(a, b) {
        if (a !== undefined && a !== null) {
            return a;
        }
        return b;
    }

    //362e2b
    function getSpan(v) {
        var width = v.scene.canvas.clientWidth;
        var height = v.scene.canvas.clientHeight;

        var scene = v.scene;
        var camera = v.scene.camera;
        var globe = v.scene.globe;
        const rightDown = camera.getPickRay(new Cesium.Cartesian2(width, height));
        const leftDown = camera.getPickRay(new Cesium.Cartesian2(0, height));
        var rightDownPosition = globe.pick(rightDown, scene);
        var leftDownPosition = globe.pick(leftDown, scene);
        var rightDownCartographic = globe.ellipsoid.cartesianToCartographic(rightDownPosition);
        var leftDownCartographic = globe.ellipsoid.cartesianToCartographic(leftDownPosition);
        var diffLon = Cesium.Math.toDegrees(rightDownCartographic.longitude) - Cesium.Math.toDegrees(leftDownCartographic.longitude);
        return diffLon / 100;
    }

    function IconEdit(cesiumViewer, options) {
        options = this._options = defaultValue(options, defined(Object.freeze) ? Object.freeze({}) : {
            change: function () {
            }
        });
        if (!defined(cesiumViewer)) {
            throw new DeveloperError('Cesium.Viewer is required');
        }

        this._viewer = cesiumViewer;
        this._lon = 117.0;
        this._lat = 39.0;
        this._alti = 10.0;
        this._scale = 1.0;
        this._converter = Cesium.Transforms.eastNorthUpToFixedFrame;
        this._icon = null;
        this._iconId = '';
        this._dragMoveEnable = false;//是否可以拖拽移动。总控
        this._dragging = false;
        this._dragOffset = {x: 0, y: 0};
        this._keyBoardMove = false;//是否使用键盘w/s/a/d键控制
        this._handler = new Cesium.ScreenSpaceEventHandler(this._viewer.canvas);
        this._dragMoveTarget = null;
        this._change = options.change;

        var _this = this;

        var deltaRadians = 1.0;
        document.addEventListener('keydown', function (e) {
            if (this._dragMoveEnable && defined(this._icon) && this._icon instanceof Cesium.Entity && this._icon.billboard) {
                switch (e.keyCode) {
                    case 87: //W
                        if (this._keyBoardMove) {
                            this.setLatitude(this._lat + getSpan(this._viewer));
                        }
                        break;
                    case 83: //S
                        if (this._keyBoardMove) {
                            this.setLatitude(this._lat - getSpan(this._viewer));
                        }
                        break;
                    case 65: //A
                        if (this._keyBoardMove) {
                            this.setLongitude(this._lon - getSpan(this._viewer));
                        }
                        break;
                    case 68: //D
                        if (this._keyBoardMove) {
                            this.setLongitude(this._lon + getSpan(this._viewer));
                        }
                        break;
                    default:
                }
            }
        }.bind(this));

//        this._handler.setInputAction(function (click) {
//            if (options.hasOwnProperty('popup') && defined(options.popup)) {
//                options.popup(click.position);
//            }
//        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        this._handler.setInputAction(function (click) {
            var pickedObject = _this._viewer.scene.pick(click.position);
            if (_this._dragMoveEnable && defined(pickedObject) && pickedObject.primitive instanceof Cesium.Billboard) {
//            	console.log('billboard')
            	if(!defined(pickedObject.id.setting)){//没有属性setting，证明不可编辑
            		return;
            	}
                _this._icon = pickedObject.id;
                _this.setIconSet(_this._icon.setting);
                _this._dragging = true;
                _this._viewer.scene.screenSpaceCameraController.enableRotate = false;
                var arrowPosition = _this._viewer.camera.pickEllipsoid(click.position);
                if (defined(arrowPosition)) {
                    var arrowCartographic = Cesium.Cartographic.fromCartesian(arrowPosition);
                    var arrowLongitude = Cesium.Math.toDegrees(arrowCartographic.longitude);
                    var arrowLatitude = Cesium.Math.toDegrees(arrowCartographic.latitude);

                    _this._dragOffset.x = Number(arrowLongitude - _this._lon);
                    _this._dragOffset.y = Number(arrowLatitude - _this._lat);
                }
                if (typeof _this._selectedChange === 'function') {
                    _this._selectedChange(pickedObject);
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
        this._handler.setInputAction(function (movement) {
            if (!defined(_this._icon)) return;
            if (_this._dragMoveEnable && _this._dragging && defined(_this._icon)) {
                var position = _this._viewer.camera.pickEllipsoid(movement.endPosition);
                if (defined(position)) {
                    var cartographic = Cesium.Cartographic.fromCartesian(position);
                    var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
                    var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
                    _this.setLongitude(Number(longitudeString) - _this._dragOffset.x);
                    _this.setLatitude(Number(latitudeString) - _this._dragOffset.y);
                }
            }
            var pickedObject = _this._viewer.scene.pick(movement.endPosition);
            if (_this._dragMoveEnable && defined(pickedObject) && pickedObject.id === _this._icon) {
                _this._icon.billboard.imageSubRegion = new Cesium.BoundingRectangle(24, 0, 24, 24);
            }
            else if(defined(_this._icon.billboard)){
                _this._icon.billboard.imageSubRegion = new Cesium.BoundingRectangle(0, 0, 24, 24);
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        this._handler.setInputAction(function (click) {
            _this._dragging = false;
            var pickedObject = _this._viewer.scene.pick(click.position);
            if (_this._dragMoveEnable && defined(pickedObject)) {
//                var position = _this._viewer.camera.pickEllipsoid(click.position);
//                if (defined(position)) {
//                    var cartographic = Cesium.Cartographic.fromCartesian(position);
//                    var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
//                    var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
//                    _this.setLongitude(Number(longitudeString) - _this._dragOffset.x);
//                    _this.setLatitude(Number(latitudeString) - _this._dragOffset.y);
//
//                    _this.lookAtIcon(false)
//                }
            }
            _this._viewer.scene.screenSpaceCameraController.enableRotate = true;
        }, Cesium.ScreenSpaceEventType.LEFT_UP);
    }

    IconEdit.prototype.loadIcon = function (iconSource, fileId, setting, completed, attributes, dataBag) {
        var _this = this;
        //数据复位
        this._lon = 117.0;
        this._lat = 39.0;
        this._alti = 10.0;
        this._scale = 1.0;
        if(defined(setting)){
        	this._lon = setting.position.x;
            this._lat = setting.position.y;
            this._alti = setting.position.h;
            this._scale = setting.scale;
        }

        //记录名称
        this._iconId = fileId || new Date().getTime();
        //计算位置和姿态
        var origin = Cesium.Cartesian3.fromDegrees(this._lon, this._lat, this._alti);
//        var iconMatrix = this._converter(origin);

        if (typeof iconSource === 'string') {
            this._icon = this._viewer.entities.add({
                id: this._iconId,
                position: origin,
                billboard: {
                    image: iconSource,
                    imageSubRegion: new Cesium.BoundingRectangle(0, 0, 24, 24),
                },
                attributes: attributes,
                dataBag: dataBag
            });

            if (typeof this._change === 'function') {
                this._change(this.getIconSet());
            }
            if (defined(completed)) {
                completed(this._icon);
            }

            this._icon.setting = this.getIconSet();
        }
        else {

        }
        
        return this._icon;
    };

    IconEdit.prototype.setIcon = function (iconId, icon, setting) {
        if (defined(icon)) {//设置模型及模型参数
            this._iconId = iconId;
            this._icon = icon;

            setting = setting || this.getIconSet();
            this._lon = setting.position.x;
            this._lat = setting.position.y;
            this._alti = setting.position.h;
            this._scale = setting.scale;
            
            this._icon.setting = this.getIconSet();
            
            this.update();
//            this.setCamera();
        }
    };

    IconEdit.prototype.setEnable = function (t) {
        this._dragMoveEnable = t;
//        if (t) {
//            this.setAltitude(0);
//        }
    };

    IconEdit.prototype.setKeyboard = function (t) {
        this._keyBoardMove = t;
    };

//    IconEdit.prototype.setCamera = function () {
//        //计算位置和姿态
//        var r = this._model.boundingSphere ? this._model.boundingSphere.radius : this._model._boundingSphere.radius;
//        var origin = Cesium.Cartesian3.fromDegrees(this._lon, this._lat, this._alti);
//
//        var hpRange = new Cesium.HeadingPitchRange();
//        hpRange.heading = this._viewer.camera.heading;
//        hpRange.pitch = this._viewer.camera.pitch;
//        hpRange.range = r * 5.0;
//        if (!this._dragging) {
//            this._viewer.camera.lookAt(origin, hpRange);
//            this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
//        }
//    };

//    IconEdit.prototype.lookAtIcon = function (t) {
//        if (t) {
//            this.setCamera();
//        }
//        else {
//            this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
//        }
//    };

    IconEdit.prototype.update = function () {
        if (!defined(this._icon)) return;

        this._icon.billboard.scale = this._scale;
        var position = Cesium.Cartesian3.fromDegrees(this._lon, this._lat, this._alti);
        this._icon.position = position;

        this._icon.setting = this.getIconSet();
        if (typeof this._change === 'function') {
            this._change(this.getIconSet());
        }
    };

    IconEdit.prototype.setScale = function (scale) {
        this._scale = scale;
        this.update();
    };

    IconEdit.prototype.setLongitude = function (lon) {
        this._lon = lon;
        this.update();
    };

    IconEdit.prototype.setLatitude = function (lat) {
        this._lat = lat;
        this.update();
    };

    IconEdit.prototype.setAltitude = function (alti) {
        this._alti = alti;
        this.update();
    };

    IconEdit.prototype.getIconSet = function () {
        return {
            position: {
                x: this._lon,
                y: this._lat,
                h: this._alti
            },
            scale: this._scale,
            hpr: {
                heading: 0,
                pitch: 0,
                roll: 0
            }
        };
    };

    IconEdit.prototype.setIconSet = function (setting, isUpdate) {
        if (defined(setting)) {
            this._lon = setting.position.x;
            this._lat = setting.position.y;
            this._alti = setting.position.h;
            this._scale = setting.scale;
        }
        else {
            return;
        }

        isUpdate = isUpdate === undefined ? true : isUpdate;
        if (isUpdate) {
            this.update();
        }
    };

    IconEdit.prototype.getIcon = function () {
        // if (defined(this._icon) && this._viewer.scene.primitives.contains(this._icon)) {
        //     this._viewer.scene.primitives.remove(this._icon);
        //     this._icon = null;
        // }
        return this._icon;
    };

    IconEdit.prototype.getId = function () {
        // if (defined(this._icon) && this._viewer.scene.primitives.contains(this._icon)) {
        //     this._viewer.scene.primitives.remove(this._icon);
        //     this._icon = null;
        // }
        return this._iconId;
    };

    IconEdit.prototype.removeIcon = function () {
        if (defined(this._icon) && this._viewer.entities.contains(this._icon)) {
            this._viewer.entities.remove(this._icon);
            this._icon = null;
            this._iconId = '';
        }
    };

    window.IconEdit = IconEdit;
})();